<template>
  <div class="v-editor-inline-wrapper" :style="{ width: width, height: height }">
    <div class="editor-container" :class="{ 'resizable': resizable }" :style="{ height: containerHeight }">
      <!-- 工具栏容器 -->
      <div :id="`${editorId}-toolbar`" class="toolbar-container"></div>

      <div class="editable-wrapper" :style="{ height: contentHeight }">
        <!-- 自定义 placeholder -->
        <div v-if="showCustomPlaceholder" class="custom-placeholder">
          {{ placeholder }}
        </div>
        <div
          :id="editorId"
          class="editable-content"
          :contenteditable="!readonly"
          :style="{ height: '100%' }"
          @click="handleContentClick"
          @keyup="handleContentChange"
          @input="handleContentChange"
        ></div>
        
        <!-- AI 行前图标与浮窗（子组件） -->
        <VAiInlineOverlay
          v-if="aiEnabled"
          :root-id="`${editorId}-ai-root`"
          :visible-marker="showAiMarker"
          :visible-popover="showAiPopover"
          :top="aiTop"
          :left="aiLeft"
          :popover-width="popoverWidth"
          :popover-offset-left="popoverOffsetLeft"
          :query="aiQuery"
          @open="openAiPopover"
          @close="closeAiPopover"
          @update:query="val => aiQuery = val"
          @submit="submitAi"
        />
      </div>

      <!-- 自定义状态栏 -->
      <div class="status-bar" v-show="showStatusBar" style="display: flex !important;">
        <div class="status-left">
          <span class="current-tag" v-if="currentTag">{{ currentTag }}</span>
        </div>
        <div class="status-right">
          <span class="word-count">{{ wordCount }} 字</span>
        </div>
      </div>

      <!-- 调整大小的拖拽手柄 -->
      <div class="resize-handle" v-if="resizable" @mousedown="startResize"></div>
    </div>
    
    <!-- 上传弹窗 -->
    <VUploadDialog
      :visible="uploadDialog.visible"
      :upload-type="uploadDialog.type"
      @close="closeUploadDialog"
      @submit="handleUploadSubmit"
    />
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
import { loadTinyMCEScript } from './utils';
import VAiInlineOverlay from './com/VAiInlineOverlay.vue';
import VUploadDialog from './com/VUploadDialog.vue';
import { useEditorCore } from './composables/useEditorCore';
import { useAiFeature } from './composables/useAiFeature';
import { useResize } from './composables/useResize';
import { registerAllCustomPlugins } from './composables/useCustomPlugins';

// ==================== Props & Emits ====================
const props = defineProps({
  modelValue: { type: String, default: '' },
  height: { type: String, default: 'auto' },
  width: { type: String, default: '100%' },
  readonly: { type: Boolean, default: false },
  placeholder: { type: String, default: '请输入内容...' },
  plugins: {
    type: Array,
    default: () => ['lists', 'link', 'image', 'table', 'code'],
  },
  toolbar: {
    type: Array,
    default: () => [
      'aiToggle | code undo redo | bold italic underline | alignleft aligncenter alignright | bullist numlist | link uploadImage uploadVideo uploadAudio',
    ],
  },
  resizable: { type: Boolean, default: true },
  showStatusBar: { type: Boolean, default: true },
  aiEnabled: { type: Boolean, default: true },
});

const emit = defineEmits(['update:modelValue', 'change', 'init', 'ready', 'resize', 'update:aiEnabled', 'upload']);

// ==================== 基础状态 ====================
const editorId = ref(`v-editor-inline-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`);

// ==================== 上传功能状态 ====================
const uploadDialog = ref({
  visible: false,
  type: 'image' // 'image' | 'video' | 'audio'
});

// ==================== 组合各个功能模块 ====================
// 编辑器核心功能
const {
  editorInstance,
  isEditorReady,
  editorHasFocus,
  showCustomPlaceholder,
  currentTag,
  wordCount,
  updateWordCount,
  updateCurrentTag,
  scrollToCursor,
  updateCustomPlaceholder,
  setEditorFocus,
} = useEditorCore(props, emit);

// AI 功能
const {
  aiState,
  showAiMarker,
  showAiPopover,
  aiTop,
  aiLeft,
  aiQuery,
  popoverWidth,
  popoverOffsetLeft,
  updateAiMarker,
  updatePopoverLayout,
  openAiPopover,
  closeAiPopover,
  submitAi,
  isFocusInsideAiOverlay,
  relayoutOnCaretMove,
  clearAiAttributes,
  isCurrentBlockEmpty,
} = useAiFeature(props, editorInstance, editorHasFocus);

// 尺寸调整功能
const {
  currentHeight,
  containerHeight,
  contentHeight,
  startResize,
} = useResize(props, emit);

// ==================== 监听器 ====================
// 监听高度变化
watch(() => props.height, (newHeight) => {
  if (newHeight) {
    currentHeight.value = newHeight;
  }
}, { immediate: true });

// 监听 AI 状态变化
watch(() => props.aiEnabled, (val) => {
  const oldVal = aiState.value;
  aiState.value = !!val;
  
  if (oldVal === !!val) return;
  
  if (editorInstance.value) {
    if (!val) {
      clearAiAttributes();
    }
    updateCustomPlaceholder(aiState.value);
    nextTick(() => updateAiMarker(editorId.value));
  }
}, { immediate: true });

watch(() => aiState.value, (val) => {
  if (!val) {
    showAiMarker.value = false;
    showAiPopover.value = false;
    aiQuery.value = '';
  } else {
    nextTick(() => updateAiMarker(editorId.value));
  }
}, { immediate: true });

// ==================== 内容处理 ====================
const handleContentClick = () => {
  updateCustomPlaceholder(aiState.value);
  updateCurrentTag();
  updateAiMarker(editorId.value);
};

const handleContentChange = () => {
  updateCustomPlaceholder(aiState.value);
  updateWordCount();
  updateCurrentTag();
  updateAiMarker(editorId.value);
};

// ==================== 上传功能处理 ====================
const openUploadDialog = (type) => {
  uploadDialog.value = {
    visible: true,
    type: type
  };
};

const closeUploadDialog = () => {
  uploadDialog.value.visible = false;
};

const handleUploadSubmit = async (data) => {
  const { file, url, type } = data;
  
  // 触发上传事件，让父组件处理实际的上传逻辑（如上传到服务器）
  emit('upload', { file, url, type });
  
  // 如果提供了 URL，直接插入到编辑器
  if (url && editorInstance.value) {
    insertMediaToEditor(url, type);
  } 
  // 如果是文件，创建临时预览 URL 并插入（父组件可以后续替换为真实 URL）
  else if (file && editorInstance.value) {
    const tempUrl = URL.createObjectURL(file);
    insertMediaToEditor(tempUrl, type);
  }
};

const insertMediaToEditor = (url, type) => {
  if (!editorInstance.value) return;
  
  let html = '';
  
  if (type === 'image') {
    html = `<img src="${url}" alt="" style="max-width: 100%;" />`;
  } else if (type === 'video') {
    html = `<video src="${url}" controls style="max-width: 100%;"></video>`;
  } else if (type === 'audio') {
    html = `<audio src="${url}" controls></audio>`;
  }
  
  editorInstance.value.insertContent(html);
};

// ==================== TinyMCE 初始化 ====================
const initTinyMCE = async () => {
  try {
    await loadTinyMCEScript();
    
    const toolbarConfig = props.toolbar.join(' | ');
    const heightConfig = typeof currentHeight.value === 'number' 
      ? currentHeight.value 
      : (parseInt(currentHeight.value) || 400);

    const config = {
      selector: `#${editorId.value}`,
      height: heightConfig,
      width: props.width,
      base_url: '/tinymce/js/tinymce/',
      theme: 'silver',
      skin: 'oxide',
      language: 'zh_CN',
      plugins: props.plugins.join(' '),
      toolbar: toolbarConfig,
      license_key: 'gpl',
      branding: false,
      menubar: false,
      inline: true,
      fixed_toolbar_container: `#${editorId.value}-toolbar`,
      inline_boundaries: false,
      toolbar_mode: 'sliding',
      toolbar_sticky: true,
      toolbar_persist: true,
      inline_toolbar: false,
      content_css: '/tinymce/editor-content.css',
      setup: setupEditor,
      init_instance_callback: initCallback,
    };

    await nextTick();
    window.tinymce.init(config);
  } catch (error) {
    console.error(`编辑器 ${editorId.value} 初始化失败:`, error);
    setTimeout(() => initTinyMCE(), 1000);
  }
};

// 编辑器设置
function setupEditor(editor) {
  // 焦点事件
  editor.on('focus', () => {
    setEditorFocus(true);
    nextTick(() => {
      updateCustomPlaceholder(aiState.value);
      updateAiMarker(editorId.value);
    });
  });

  editor.on('blur', () => {
    setEditorFocus(false);
    nextTick(() => {
      updateCustomPlaceholder(aiState.value);
      updateAiMarker(editorId.value);
    });
  });

  // 内容变化
  editor.on('Change', (e) => {
    const content = editor.getContent();
    updateCustomPlaceholder(aiState.value);
    emit('update:modelValue', content);
    emit('change', content, e);
    
    // 如果浮窗打开且查询为空，且用户在编辑器中输入内容，则关闭浮窗
    // 只有在编辑器有焦点时才关闭（表示用户在编辑器内输入）
    if (showAiPopover.value && !aiQuery.value && editorHasFocus.value) {
      closeAiPopover(editorId.value);
    }
    
    nextTick(() => {
      updateWordCount();
      updateCurrentTag();
      scrollToCursor();
      updateAiMarker(editorId.value);
      updatePopoverLayout(editorId.value);
    });
  });

  // 节点变化
  editor.on('NodeChange', () => {
    if (showAiPopover.value && isFocusInsideAiOverlay(editorId.value)) return;
    
    nextTick(() => {
      updateCurrentTag();
      updateAiMarker(editorId.value);
      updatePopoverLayout(editorId.value);
      relayoutOnCaretMove(editorId.value);
    });
  });

  // 选择变化
  editor.on('SelectionChange', () => {
    if (showAiPopover.value && isFocusInsideAiOverlay(editorId.value)) return;
    
    nextTick(() => {
      updateCurrentTag();
      updateAiMarker(editorId.value);
      updatePopoverLayout(editorId.value);
      relayoutOnCaretMove(editorId.value);
    });
  });

  // 键盘事件
  editor.on('KeyUp', (e) => {
    if (showAiPopover.value && isFocusInsideAiOverlay(editorId.value)) return;
    updateCustomPlaceholder(aiState.value);
    
    // 方向键、回车键移动光标时，如果浮窗打开且查询为空，则关闭浮窗
    const isNavigationKey = e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 37 || e.keyCode === 39;
    if (showAiPopover.value && !aiQuery.value && isNavigationKey) {
      closeAiPopover(editorId.value);
    }
    
    if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 33 || e.keyCode === 34) {
      nextTick(() => scrollToCursor());
    }
    nextTick(() => {
      updateAiMarker(editorId.value);
      updatePopoverLayout(editorId.value);
      relayoutOnCaretMove(editorId.value);
    });
  });

  editor.on('KeyDown', (e) => {
    if (e.keyCode === 13) {
      nextTick(() => {
        setTimeout(() => {
          scrollToCursor();
          updateAiMarker(editorId.value);
          updatePopoverLayout(editorId.value);
          relayoutOnCaretMove(editorId.value);
        }, 50);
      });
    }
    
    // 空格键打开 AI 浮窗（当 AI 开启且当前行为空时）
    if (e.keyCode === 32) {
      if (aiState.value && isCurrentBlockEmpty()) {
        e.preventDefault();
        e.stopPropagation();
        nextTick(() => {
          openAiPopover(editorId.value);
          updateAiMarker(editorId.value);
          updatePopoverLayout(editorId.value);
        });
      }
    }
  });

  // 注册所有自定义插件
  registerAllCustomPlugins(editor, {
    // AI 相关
    aiEnabled: aiState.value,
    aiState,
    emit,
    closeAiPopover,
    clearAiAttributes,
    updateCustomPlaceholder,
    updateAiMarker,
    editorId: editorId.value,
    watch,
    nextTick,
    // 上传相关
    openUploadDialog,
  });
}

// 初始化回调
function initCallback(editor) {
  console.log(`编辑器 ${editorId.value} 初始化完成`);
  editorInstance.value = editor;
  isEditorReady.value = true;
  
  if (props.modelValue) {
    editor.setContent(props.modelValue);
  }
  
  setEditorFocus(editor.hasFocus());
  updateCustomPlaceholder(aiState.value);

  try {
    const body = editor.getBody();
    if (body && body.firstChild) {
      editor.selection.setCursorLocation(body.firstChild, 0);
    } else if (body) {
      editor.selection.setCursorLocation(body, 0);
    }
  } catch (err) {
    console.warn(`编辑器 ${editorId.value} 设置初始光标失败:`, err);
  }

  setTimeout(() => {
    try {
      const toolbarContainer = document.getElementById(`${editorId.value}-toolbar`);
      if (toolbarContainer) {
        toolbarContainer.style.display = 'block';
        toolbarContainer.style.visibility = 'visible';
      }

      const container = editor.getContainer();
      const toolbar = container.querySelector('.tox-toolbar');
      if (toolbar) {
        toolbar.style.display = 'flex';
        toolbar.style.visibility = 'visible';
      }

      updateWordCount();
      updateCurrentTag();
      updateAiMarker(editorId.value);
      
      console.log(`编辑器 ${editorId.value} 工具栏设置完成`);
    } catch (error) {
      console.warn(`编辑器 ${editorId.value} 设置工具栏可见性时出错:`, error);
    }
  }, 100);
  
  const editable = document.getElementById(editorId.value);
  const onScroll = () => {
    requestAnimationFrame(() => {
      updateAiMarker(editorId.value);
      updatePopoverLayout(editorId.value);
    });
  };
  if (editable) {
    editable.addEventListener('scroll', onScroll, { passive: true });
  }
  editor._aiScrollHandler = onScroll;
  
  emit('init', editor);
  emit('ready', editor);
}

// 销毁编辑器
const destroyEditor = () => {
  if (editorInstance.value && window.tinymce) {
    try {
      const editable = document.getElementById(editorId.value);
      const onScroll = editorInstance.value?._aiScrollHandler;
      if (editable && onScroll) {
        editable.removeEventListener('scroll', onScroll);
      }
      window.tinymce.remove(editorInstance.value);
    } catch (error) {
      console.warn('销毁编辑器时出错:', error);
    }
    editorInstance.value = null;
    isEditorReady.value = false;
  }
};

// ==================== 生命周期 ====================
onMounted(() => {
  initTinyMCE();
  
  // 点击外部关闭浮窗
  const onDocMouseDown = (e) => {
    const aiRoot = document.getElementById(`${editorId.value}-ai-root`);
    const editable = document.getElementById(editorId.value);
    
    // 点击浮窗外部区域时关闭（包括点击编辑器内容）
    if (showAiPopover.value && aiRoot && !aiRoot.contains(e.target)) {
      // 如果查询为空，则关闭浮窗
      if (!aiQuery.value) {
        closeAiPopover(editorId.value);
      }
    }
  };
  document.addEventListener('mousedown', onDocMouseDown);
  
  onBeforeUnmount(() => {
    document.removeEventListener('mousedown', onDocMouseDown);
  });
});

onBeforeUnmount(() => {
  destroyEditor();
});

// ==================== 导出方法供外部使用 ====================
defineExpose({
  getEditor: () => editorInstance.value,
  getContent: () => editorInstance.value?.getContent() || '',
  setContent: (content) => editorInstance.value?.setContent(content),
  focus: () => editorInstance.value?.focus(),
  insertMediaToEditor,
});
</script>

<style scoped>
.v-editor-inline-wrapper {
  display: flex;
  flex-direction: column;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}

.editor-container {
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background-color: #fff;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: none;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  position: relative;
  min-height: 116px !important;
}

.editor-container:focus-within {
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

.toolbar-container {
  min-height: 48px;
  background: #ffffff;
  border-bottom: none;
  border-top-left-radius: 6px;
  border-top-right-radius: 6px;
  padding: 0;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  display: flex!important;
  align-items: center;
}

.editable-wrapper {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.custom-placeholder {
  position: absolute;
  top: 28px;
  left: 80px;
  color: #9ca3af;
  font-style: normal;
  pointer-events: none;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  z-index: 1;
}

.editable-content {
  min-height: 30px !important;
  padding: 24px 80px;
  outline: none;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: #333333;
  background-color: #fff;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  box-sizing: border-box;
}

.status-bar {
  height: 48px;
  min-height: 48px;
  background: #f9fafb;
  border-top: 1px solid #e5e7eb;
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: #6b7280;
  flex-shrink: 0;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
}

.status-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.status-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.current-tag {
  font-weight: 500;
  color: #374151;
  background: #e5e7eb;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
}

.word-count {
  color: #6b7280;
}

.resize-handle {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 8px;
  cursor: ns-resize;
  background: transparent;
  z-index: 10;
}

.resize-handle:hover {
  background: rgba(59, 130, 246, 0.1);
}

.editor-container.resizable {
  resize: none;
}
</style>
